<!-- 日历视图选择器 -->
<template>
  <div class="calendar-view-select">
    <el-calendar ref="calendar" v-model="currentDate" v-bind="calendarProps">
      <template #header="{ date }">
        <div class="el-calendar__title">{{ date }}</div>
        <div class="el-calendar__button-group">
          <el-button-group>
            <el-button size="small" @click="selectDate('prev-month')">
              <Icon icon="ep:arrow-left" />
            </el-button>
            <el-button size="small" type="primary" @click="selectDate('today')"> 今日 </el-button>
            <el-button size="small" @click="selectDate('next-month')">
              <Icon icon="ep:arrow-right" />
            </el-button>
          </el-button-group>
        </div>
      </template>
      <template #date-cell="{ data }">
        <div class="calendar-cell">
          <slot name="dateCell" :data="data">
            <span>{{ data.day.split('-')[2] }}</span>
            <div class="calendar-dot-container">
              <template v-for="(dot, index) in getShowDots(data.day)" :key="index">
                <span class="calendar-dot" :class="dot.class" :style="dot.style"></span>
              </template>
            </div>
          </slot>
        </div>
      </template>
    </el-calendar>

    <div class="legend" v-if="showLegend && legendItems && legendItems.length > 0">
      <slot name="legend">
        <template v-for="(item, index) in legendItems" :key="index">
          <div class="legend-item">
            <span class="calendar-dot" :class="item.class" :style="item.style"></span>
            <span>{{ item.text }}</span>
          </div>
        </template>
      </slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { CalendarDateType, CalendarInstance } from 'element-plus'
import { formatDate } from '@/utils/formatTime'
// 定义日程点类型
export interface CalendarDot {
  class?: string | string[] | Record<string, boolean>
  style?: Record<string, string>
}

export interface LegendItem {
  class?: string | string[] | Record<string, boolean>
  style?: Record<string, string>
  text: string
}

// 定义组件属性
const props = withDefaults(
  defineProps<{
    modelValue: Date
    calendarProps?: Record<string, any>
    showLegend?: boolean
    legendItems?: LegendItem[]
    dotCalculator?: (day: string) => CalendarDot[]
  }>(),
  {
    modelValue: () => new Date(),
    calendarProps: () => ({}),
    showLegend: true,
    legendItems: () => [],
    dotCalculator: undefined
  }
)

// 定义事件
const emit = defineEmits<{
  'update:modelValue': [value: Date]
  'month-change': [value: string, value: Date]
  change: [{ day: string; date: Date }]
}>()

// 日历组件实例
const calendar = ref<CalendarInstance>()
const oldMonth = ref('') // 上一次查询的月份
// 当前选中的日期
const currentDate = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

/**
 * 获取指定日期的状态点
 */
const getShowDots = (day: string) => {
  // 如果提供了自定义点计算方法，则使用它
  if (props.dotCalculator) {
    return props.dotCalculator(day)
  }
  // 默认返回空数组
  return []
}

/**
 * 选择日期
 */
const selectDate = (val: CalendarDateType) => {
  if (!calendar.value) return
  calendar.value.selectDate(val)
}

/** 监听日期变化 */
watch(currentDate, (val) => {
  const month = formatDate(val, 'YYYYMM')
  const day = formatDate(val, 'YYYY-MM-DD')

  // 如果月份变化了，重新获取月份数据
  if (oldMonth.value !== month) {
    oldMonth.value = month
    emit('month-change', month, val)
  }
  if (day) {
    emit('change', { day, date: val })
  }
})
defineExpose({
  selectDate,
  calendar
})
</script>

<style lang="scss" scoped>
.calendar-view-select {
  width: 100%;
}

.legend {
  padding: 12px;
  margin-top: 12px;
  font-size: 14px;
  color: #606266;
  text-align: center;

  .legend-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-right: 12px;

    &:last-child {
      margin-right: 0;
    }
  }
}

.calendar-cell {
  position: relative;
  display: flex;
  cursor: pointer;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.calendar-dot-container {
  display: flex;
  margin-top: 4px;
  gap: 4px;
}

.calendar-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  vertical-align: middle;
  border-radius: 100px;
}

:deep() {
  .el-calendar__header {
    padding: 2px;
  }

  .el-calendar__body {
    padding: 0;
  }

  .el-calendar-day {
    height: 50px !important;
    text-align: center;
  }

  .el-calendar-table td.is-selected {
    background-color: var(--el-color-primary-light-9) !important;
  }
}
</style>
